package org.zhaya.sdk.constant;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.zhaya.sdk.processors.condition.ProcessorEnum;

import java.util.Map;
import java.util.Objects;

/**
 * @Author Ryan Yang
 * @Date 2022/10/10 5:27 下午
 */

public enum OperatorEnum {

    gt {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, "gt", "mathComparator");
        }
    }, lt {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, "lt", "mathComparator");
        }
    }, gte {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, "gte", "mathComparator");
        }
    }, lte {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, "lte", "mathComparator");
        }
    }, eq {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field)) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            if (Objects.isNull(value)) {
                return conditionMap(field, value, "notExist", "notExist");
            }
            return conditionMap(field, Lists.newArrayList(value), ProcessorEnum.possibleValues.name(), "hasValue");
        }
    }, ne {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field)) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            if (Objects.isNull(value)) {
                return conditionMap(field, value, "exists", "exists");
            }
            return conditionMap(field, Lists.newArrayList(value), ProcessorEnum.possibleValues.name(), "hasntValue");
        }
    }, reg {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, "regex", "matchRegex");
        }
    }, def {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            return conditionMap(field, value, StringUtils.EMPTY, "defaultCondition");
        }
    }, startWith {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, ProcessorEnum.value.name(), "startWith");
        }
    }, in {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, ProcessorEnum.value.name(), "include");
        }
    }, nin {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, ProcessorEnum.value.name(), "exclude");
        }
    }, exists {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            return conditionMap(field, value, "exists", "exists");
        }
    }, notExist {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            return conditionMap(field, value, "notExist", "notExist");
        }
    }, belong {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, "inCollection", "in");
        }
    }, notBelong {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (StringUtils.isBlank(field) || value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, "notInCollection", "notIn");
        }
    }, cql {
        @Override
        public Map<String, Object> transfer(String field, Object value) {
            if (value == null || StringUtils.isBlank(value.toString())) {
                throw new RuntimeException(FILED_MISSING_ERROR_MSG);
            }
            return conditionMap(field, value, "cql", "cql");
        }
    };

    private static final String FILED_MISSING_ERROR_MSG = "Some fields in the component condition are missing";

    /**
     * {\"mathComparator\":{\"field\": \"day_diff\",\"gte\": 0}}
     * {\"matchRegex\":{\"field\": \"day_diff\",\"regex\": "\\d+",\"caseInsensitive\":true,\"matchPartOfValue\":true}
     *
     * @param field
     * @param value
     * @return
     */
    public abstract Map<String, Object> transfer(String field, Object value);

    private static Map<String, Object> baseMap(String field, Object value, String base) {
        Map<String, Object> map = Maps.newHashMapWithExpectedSize(4);
        map.put(ProcessorEnum.field.name(), field);
        if ((!"exists".equals(base)) || (!"notExist".equals(base))) {
            map.put(base, value);
        }
        if ("regex".equals(base)) {
            map.put("caseInsensitive", false);
            map.put("matchPartOfValue", false);
        }
        return map;
    }

    private static Map<String, Object> conditionMap(String field, Object value, String base, String condition) {
        Map<String, Object> baseMap;
        if ("defaultCondition".equals(condition)) {
            baseMap = Maps.newHashMap();
        } else {
            baseMap = baseMap(field, value, base);
        }

        Map<String, Object> conditionMap = Maps.newHashMapWithExpectedSize(2);
        conditionMap.put(condition, baseMap);
        return conditionMap;
    }
}
